#pragma once
#include "stdafx.h"

struct ImagePointComp {
	bool operator () ( const CvPoint & lhs, const CvPoint & rhs )
	{
		if (lhs.y < rhs.y)
		{
			return true;
		}
		else if (lhs.y > rhs.y)
		{
			return false;
		}
		else if (lhs.x < rhs.x)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

struct FeaturePoint
{
	CvPoint position;
	int Nb;
	
	FeaturePoint()
	{
		this->Nb = 0;
		this->position = cvPoint(0,0);
	}

	bool operator < ( const FeaturePoint & rhs ) const
	{
		if (this->position.y < rhs.position.y)
		{
			return true;
		}
		else if (this->position.y > rhs.position.y)
		{
			return false;
		}
		else if (this->position.x < rhs.position.x)
		{
			return true;
		}
		else
		{
			return false;
		}
	}	
	
	bool operator == (const FeaturePoint &point) const
	{
		if ((this->position.x == point.position.x) && (this->position.y == point.position.y))
		{
			return true;
		}
		return false;
	}

	bool operator != (const FeaturePoint &point) const
	{
		if (this->position.x != point.position.x) 
		{
			return true;
		}
		else if (this->position.y != point.position.y)
		{
			return true;
		}
		return false;
	}

	void operator = (const FeaturePoint &point)
	{
		this->position = point.position;
		this->Nb = point.Nb;
	}
};

class ContourChain;

struct ContourPoint
{
	CvPoint position;
	ContourPoint* next;
	ContourPoint* prev;
	ContourChain* owner;
};

class ContourChain
{
public:
	// Constructor
	ContourChain();
	// Destructor
	~ContourChain();

	// Insert an element to contour chain
	void insert(CvPoint element);
	// Get a contour segment
	bool getSegment(ContourPoint* const startPoint, ContourPoint* const endPoint, set<ContourPoint*> &result);
	// Get a set of backward contour points
	ContourPoint* forward(ContourPoint* start_point, int step);
	// Get a set of forward contour points
	ContourPoint* backward(ContourPoint* start_point, int step);
	// Get contour chain's length
	int getLength();
	// Get contour point based in its position
	ContourPoint* get(CvPoint point);
	// Get head of chain
	ContourPoint* getHead();
	// Get head of chain
	ContourPoint* getTail();
private:
	ContourPoint* head;
	ContourPoint* tail;
	int length;
};

struct StrokeNode
{

	set<CvPoint,ImagePointComp> elements;
	map<StrokeNode*, vector<CvPoint>> spwt;
	vector<CvPoint> polygon_vertex;
	bool isAmbigousZone;
	vector<StrokeNode*> neighbours;
	map<StrokeNode*,pair<CvPoint,CvPoint>> starting_pointers;
	int id;
	bool isolated;
	StrokeNode()
	{
		this->isAmbigousZone = false;
		this->isolated = true;
		this->elements.clear();
		this->spwt.clear();
		this->polygon_vertex.clear();
			
	}
	~StrokeNode()
	{
		this->elements.clear();
		this->spwt.clear();
		this->polygon_vertex.clear();
		this->neighbours.clear();
	}
	void create_link(StrokeNode *neighbour)
	{
		this->neighbours.push_back(neighbour);
	}
	void create_starting_pointers(CvPoint p1, CvPoint p2, StrokeNode* ambigous_zone)
	{
		pair<CvPoint,CvPoint> pointers = make_pair(p1,p2);
		this->starting_pointers[ambigous_zone] = pointers;
	}
	CvPoint gravity_center()
	{
		set<CvPoint,ImagePointComp>::iterator it;
		CvPoint retval;
		retval.x = 0;
		retval.y = 0;
		if (this->elements.size()> 0)
		{
			int count = 0;
			for(it = this->elements.begin(); it!= this->elements.end(); it++)
			{
				retval.x+= (*it).x;
				retval.y+= (*it).y;
				count++;
			}
			
			retval.x = retval.x / count;
			retval.y = retval.y / count;
		}

		return retval;
	}
};
